<!doctype html><html lang=en-us><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content="虽然 C++ 模板最初被 Bjarne Stroustrup 称为参数化类型，但是实际上其工作方式更像一个受限制的高级版宏，”模板“这个名称更加合适。
这里使用 C++ 模板的非类型参数特性来实现一些数列的编译期计算。
阶乘数列 $$ F_i = \begin{cases} 1 &amp;amp; i = 0 \\ iF_{i-1} &amp;amp; i &amp;gt; 0 \end{cases} $$
template &amp;lt;int num&amp;gt; class Factorial { public: static const int value = num * Factorial&amp;lt;num - 1&amp;gt;::value; }; template &amp;lt;&amp;gt; class Factorial&amp;lt;0&amp;gt; { public: static const int value = 1; }; int main() { cout &amp;lt;&amp;lt; Factorial&amp;lt;10&amp;gt;::value &amp;lt;&amp;lt; endl; } 为什么这是编译期运算呢？可以从两个方面了解。
关闭编译器所有优化。
g++ -S fac."><title>C++ 模板实现编译期计算数列</title><link rel=canonical href=https://stardustdl.gitee.io/posts/learning/cpp-template-seq/><link rel=stylesheet href=/scss/style.min.css><meta property="og:title" content="C++ 模板实现编译期计算数列"><meta property="og:description" content="虽然 C++ 模板最初被 Bjarne Stroustrup 称为参数化类型，但是实际上其工作方式更像一个受限制的高级版宏，”模板“这个名称更加合适。
这里使用 C++ 模板的非类型参数特性来实现一些数列的编译期计算。
阶乘数列 $$ F_i = \begin{cases} 1 &amp;amp; i = 0 \\ iF_{i-1} &amp;amp; i &amp;gt; 0 \end{cases} $$
template &amp;lt;int num&amp;gt; class Factorial { public: static const int value = num * Factorial&amp;lt;num - 1&amp;gt;::value; }; template &amp;lt;&amp;gt; class Factorial&amp;lt;0&amp;gt; { public: static const int value = 1; }; int main() { cout &amp;lt;&amp;lt; Factorial&amp;lt;10&amp;gt;::value &amp;lt;&amp;lt; endl; } 为什么这是编译期运算呢？可以从两个方面了解。
关闭编译器所有优化。
g++ -S fac."><meta property="og:url" content="https://stardustdl.gitee.io/posts/learning/cpp-template-seq/"><meta property="og:site_name" content="StardustDL's Blog"><meta property="og:type" content="article"><meta property="article:section" content="Posts"><meta property="article:tag" content="C++"><meta property="article:tag" content="编程语言"><meta property="article:published_time" content="2020-07-23T13:23:31+08:00"><meta property="article:modified_time" content="2020-07-23T13:23:31+08:00"><meta name=twitter:title content="C++ 模板实现编译期计算数列"><meta name=twitter:description content="虽然 C++ 模板最初被 Bjarne Stroustrup 称为参数化类型，但是实际上其工作方式更像一个受限制的高级版宏，”模板“这个名称更加合适。
这里使用 C++ 模板的非类型参数特性来实现一些数列的编译期计算。
阶乘数列 $$ F_i = \begin{cases} 1 &amp;amp; i = 0 \\ iF_{i-1} &amp;amp; i &amp;gt; 0 \end{cases} $$
template &amp;lt;int num&amp;gt; class Factorial { public: static const int value = num * Factorial&amp;lt;num - 1&amp;gt;::value; }; template &amp;lt;&amp;gt; class Factorial&amp;lt;0&amp;gt; { public: static const int value = 1; }; int main() { cout &amp;lt;&amp;lt; Factorial&amp;lt;10&amp;gt;::value &amp;lt;&amp;lt; endl; } 为什么这是编译期运算呢？可以从两个方面了解。
关闭编译器所有优化。
g++ -S fac."><link rel="shortcut icon" href=/favicon.png><script type=application/javascript>var doNotTrack=!1;doNotTrack||(function(a,e,f,g,b,c,d){a.GoogleAnalyticsObject=b,a[b]=a[b]||function(){(a[b].q=a[b].q||[]).push(arguments)},a[b].l=1*new Date,c=e.createElement(f),d=e.getElementsByTagName(f)[0],c.async=1,c.src=g,d.parentNode.insertBefore(c,d)}(window,document,'script','https://www.google-analytics.com/analytics.js','ga'),ga('create','UA-111573521-1','auto'),ga('send','pageview'))</script></head><body class="article-page has-toc"><script>(function(){const a='StackColorScheme';localStorage.getItem(a)||localStorage.setItem(a,"auto")})()</script><script>(function(){const b='StackColorScheme',a=localStorage.getItem(b),c=window.matchMedia('(prefers-color-scheme: dark)').matches===!0;a=='dark'||a==='auto'&&c?document.documentElement.dataset.scheme='dark':document.documentElement.dataset.scheme='light'})()</script><div class="container main-container flex
extended"><div id=article-toolbar><a href=/ class=back-home><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-chevron-left" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><polyline points="15 6 9 12 15 18"/></svg><span>Back</span></a></div><main class="main full-width"><article class=main-article><header class=article-header><div class=article-details><header class=article-category><a href=/categories/learning/>Learning</a></header><h2 class=article-title><a href=/posts/learning/cpp-template-seq/>C++ 模板实现编译期计算数列</a></h2><footer class=article-time><div><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-calendar-time" width="56" height="56" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><path d="M11.795 21H5a2 2 0 01-2-2V7a2 2 0 012-2h12a2 2 0 012 2v4"/><circle cx="18" cy="18" r="4"/><path d="M15 3v4"/><path d="M7 3v4"/><path d="M3 11h16"/><path d="M18 16.496V18l1 1"/></svg><time class=article-time--published>Jul 23, 2020</time></div><div><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-clock" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 15 15"/></svg><time class=article-time--reading>3 minute read</time></div></footer></div></header><section class=article-content><p>虽然 C++ 模板最初被 Bjarne Stroustrup 称为参数化类型，但是实际上其工作方式更像一个受限制的高级版宏，”模板“这个名称更加合适。</p><p>这里使用 C++ 模板的非类型参数特性来实现一些数列的编译期计算。</p><h2 id=阶乘数列>阶乘数列</h2><p>$$
F_i = \begin{cases}
1 & i = 0 \\ iF_{i-1} & i > 0
\end{cases}
$$</p><div class=highlight><pre class=chroma><code class=language-cpp data-lang=cpp><span class=k>template</span> <span class=o>&lt;</span><span class=kt>int</span> <span class=n>num</span><span class=o>&gt;</span>
<span class=k>class</span> <span class=nc>Factorial</span>
<span class=p>{</span>
<span class=k>public</span><span class=o>:</span>
    <span class=k>static</span> <span class=k>const</span> <span class=kt>int</span> <span class=n>value</span> <span class=o>=</span> <span class=n>num</span> <span class=o>*</span> <span class=n>Factorial</span><span class=o>&lt;</span><span class=n>num</span> <span class=o>-</span> <span class=mi>1</span><span class=o>&gt;::</span><span class=n>value</span><span class=p>;</span>
<span class=p>};</span>

<span class=k>template</span> <span class=o>&lt;&gt;</span>
<span class=k>class</span> <span class=nc>Factorial</span><span class=o>&lt;</span><span class=mi>0</span><span class=o>&gt;</span>
<span class=p>{</span>
<span class=k>public</span><span class=o>:</span>
    <span class=k>static</span> <span class=k>const</span> <span class=kt>int</span> <span class=n>value</span> <span class=o>=</span> <span class=mi>1</span><span class=p>;</span>
<span class=p>};</span>

<span class=kt>int</span> <span class=nf>main</span><span class=p>()</span>
<span class=p>{</span>
    <span class=n>cout</span> <span class=o>&lt;&lt;</span> <span class=n>Factorial</span><span class=o>&lt;</span><span class=mi>10</span><span class=o>&gt;::</span><span class=n>value</span> <span class=o>&lt;&lt;</span> <span class=n>endl</span><span class=p>;</span>
<span class=p>}</span>
</code></pre></div><p>为什么这是编译期运算呢？可以从两个方面了解。</p><p>关闭编译器所有优化。</p><div class=highlight><pre class=chroma><code class=language-sh data-lang=sh>g++ -S fac.cpp -O0
</code></pre></div><p>查看编译得到的汇编代码。</p><div class=highlight><pre class=chroma><code class=language-diff data-lang=diff>main:
.LFB1522:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
<span class=gd>-	movl	$3628800, %esi
</span><span class=gd></span>	leaq	_ZSt4cout(%rip), %rdi
	call	_ZNSolsEi@PLT
	movq	%rax, %rdx
	movq	_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GOTPCREL(%rip), %rax
	movq	%rax, %rsi
	movq	%rdx, %rdi
	call	_ZNSolsEPFRSoS_E@PLT
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
</code></pre></div><p>可以看到在标注的那一行，编译期直接将阶乘结果写到了汇编代码中。</p><p>当运算结果超出 int 范围时，能否编译通过？</p><p>更改 <code>main</code> 函数：</p><div class=highlight><pre class=chroma><code class=language-cpp data-lang=cpp><span class=kt>int</span> <span class=nf>main</span><span class=p>()</span>
<span class=p>{</span>
    <span class=n>cout</span> <span class=o>&lt;&lt;</span> <span class=n>Factorial</span><span class=o>&lt;</span><span class=mi>20</span><span class=o>&gt;::</span><span class=n>value</span> <span class=o>&lt;&lt;</span> <span class=n>endl</span><span class=p>;</span>
<span class=p>}</span>
</code></pre></div><p>再次编译：</p><div class=highlight><pre class=chroma><code class=language-diff data-lang=diff>fac.cpp: In instantiation of ‘const int Factorial&lt;13&gt;::value’:
fac.cpp:8:34:   recursively required from ‘const int Factorial&lt;19&gt;::value’
fac.cpp:8:34:   required from ‘const int Factorial&lt;20&gt;::value’
fac.cpp:20:28:   required from here
<span class=gd>- fac.cpp:8:34: warning: integer overflow in expression of type ‘int’ results in ‘1932053504’ [-Woverflow]
</span><span class=gd></span>    8 |     static const int value = num * Factorial&lt;num - 1&gt;::value;
      |                              ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
fac.cpp:8:22: error: overflow in constant expression [-fpermissive]
    8 |     static const int value = num * Factorial&lt;num - 1&gt;::value;
      |                      ^~~~~
fac.cpp:8:22: error: overflow in constant expression [-fpermissive]
</code></pre></div><p>可以看到编译器计算出了结果，同时也发现了溢出错误。</p><h2 id=斐波那契数列>斐波那契数列</h2><p>$$
F_i = \begin{cases}
0 & i = 0 \\ 1 & i = 1 \\ F_{i-1} + F_{i-2} & i > 1
\end{cases}
$$</p><div class=highlight><pre class=chroma><code class=language-cpp data-lang=cpp><span class=k>template</span> <span class=o>&lt;</span><span class=kt>int</span> <span class=n>num</span><span class=o>&gt;</span>
<span class=k>class</span> <span class=nc>Fibonacci</span>
<span class=p>{</span>
<span class=k>public</span><span class=o>:</span>
    <span class=k>static</span> <span class=k>const</span> <span class=kt>int</span> <span class=n>value</span> <span class=o>=</span> <span class=n>Fibonacci</span><span class=o>&lt;</span><span class=n>num</span> <span class=o>-</span> <span class=mi>1</span><span class=o>&gt;::</span><span class=n>value</span> <span class=o>+</span> <span class=n>Fibonacci</span><span class=o>&lt;</span><span class=n>num</span> <span class=o>-</span> <span class=mi>2</span><span class=o>&gt;::</span><span class=n>value</span><span class=p>;</span>
<span class=p>};</span>

<span class=k>template</span> <span class=o>&lt;&gt;</span>
<span class=k>class</span> <span class=nc>Fibonacci</span><span class=o>&lt;</span><span class=mi>0</span><span class=o>&gt;</span>
<span class=p>{</span>
<span class=k>public</span><span class=o>:</span>
    <span class=k>static</span> <span class=k>const</span> <span class=kt>int</span> <span class=n>value</span> <span class=o>=</span> <span class=mi>0</span><span class=p>;</span>
<span class=p>};</span>

<span class=k>template</span> <span class=o>&lt;&gt;</span>
<span class=k>class</span> <span class=nc>Fibonacci</span><span class=o>&lt;</span><span class=mi>1</span><span class=o>&gt;</span>
<span class=p>{</span>
<span class=k>public</span><span class=o>:</span>
    <span class=k>static</span> <span class=k>const</span> <span class=kt>int</span> <span class=n>value</span> <span class=o>=</span> <span class=mi>1</span><span class=p>;</span>
<span class=p>};</span>
</code></pre></div><h2 id=组合数>组合数</h2><p>$$
F_{n,m} = \begin{cases}
1 & m = 0 \\ 0 & n = 0 \wedge m > 0 \\ F_{n-1,m-1} + F_{n-1,m} & \text{otherwise}
\end{cases}
$$</p><p>上述递推式可以蕴含 $n>m$ 时 $F_{n,m}=0$ 的情况。</p><div class=highlight><pre class=chroma><code class=language-cpp data-lang=cpp><span class=k>template</span> <span class=o>&lt;</span><span class=kt>int</span> <span class=n>n</span><span class=p>,</span> <span class=kt>int</span> <span class=n>m</span><span class=o>&gt;</span>
<span class=k>class</span> <span class=nc>Combinatorial</span>
<span class=p>{</span>
<span class=k>public</span><span class=o>:</span>
    <span class=k>static</span> <span class=k>const</span> <span class=kt>int</span> <span class=n>value</span> <span class=o>=</span> <span class=n>Combinatorial</span><span class=o>&lt;</span><span class=n>n</span> <span class=o>-</span> <span class=mi>1</span><span class=p>,</span> <span class=n>m</span><span class=o>&gt;::</span><span class=n>value</span> <span class=o>+</span> <span class=n>Combinatorial</span><span class=o>&lt;</span><span class=n>n</span> <span class=o>-</span> <span class=mi>1</span><span class=p>,</span> <span class=n>m</span> <span class=o>-</span> <span class=mi>1</span><span class=o>&gt;::</span><span class=n>value</span><span class=p>;</span>
<span class=p>};</span>

<span class=k>template</span> <span class=o>&lt;</span><span class=kt>int</span> <span class=n>m</span><span class=o>&gt;</span>
<span class=k>class</span> <span class=nc>Combinatorial</span><span class=o>&lt;</span><span class=mi>0</span><span class=p>,</span> <span class=n>m</span><span class=o>&gt;</span>
<span class=p>{</span>
<span class=k>public</span><span class=o>:</span>
    <span class=k>static</span> <span class=k>const</span> <span class=kt>int</span> <span class=n>value</span> <span class=o>=</span> <span class=mi>0</span><span class=p>;</span>
<span class=p>};</span>

<span class=k>template</span> <span class=o>&lt;</span><span class=kt>int</span> <span class=n>n</span><span class=o>&gt;</span>
<span class=k>class</span> <span class=nc>Combinatorial</span><span class=o>&lt;</span><span class=n>n</span><span class=p>,</span> <span class=mi>0</span><span class=o>&gt;</span>
<span class=p>{</span>
<span class=k>public</span><span class=o>:</span>
    <span class=k>static</span> <span class=k>const</span> <span class=kt>int</span> <span class=n>value</span> <span class=o>=</span> <span class=mi>1</span><span class=p>;</span>
<span class=p>};</span>

<span class=k>template</span> <span class=o>&lt;&gt;</span>
<span class=k>class</span> <span class=nc>Combinatorial</span><span class=o>&lt;</span><span class=mi>0</span><span class=p>,</span> <span class=mi>0</span><span class=o>&gt;</span>
<span class=p>{</span>
<span class=k>public</span><span class=o>:</span>
    <span class=k>static</span> <span class=k>const</span> <span class=kt>int</span> <span class=n>value</span> <span class=o>=</span> <span class=mi>1</span><span class=p>;</span>
<span class=p>};</span>
</code></pre></div><p>因为 <code>class Combinatorial&lt;0, m></code> 和 <code>class Combinatorial&lt;n, 0></code> 均能匹配 $F_{0,0}$ 的情况，所以需要额外加入一个模板。</p><p>如果不加入，编译器会自动检查出递归式的定义在 $(0,0)$ 处出现了冲突。</p><div class=highlight><pre class=chroma><code class=language-diff data-lang=diff>comb.cpp: In instantiation of ‘const int Combinatorial&lt;1, 1&gt;::value’:
comb.cpp:8:61:   recursively required from ‘const int Combinatorial&lt;9, 3&gt;::value’
comb.cpp:8:61:   required from ‘const int Combinatorial&lt;10, 3&gt;::value’
comb.cpp:28:35:   required from here
<span class=gd>- comb.cpp:8:61: error: ambiguous template instantiation for ‘class Combinatorial&lt;0, 0&gt;’
</span><span class=gd></span>    8 |     static const int value = Combinatorial&lt;n - 1, m&gt;::value + Combinatorial&lt;n - 1, m - 1&gt;::value;
      |                                                       ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
comb.cpp:12:7: note: candidates are: ‘template&lt;int m&gt; class Combinatorial&lt;0, m&gt; [with int m = 0]’
   12 | class Combinatorial&lt;0, m&gt;
      |       ^~~~~~~~~~~~~~~~~~~
comb.cpp:19:7: note:                 ‘template&lt;int n&gt; class Combinatorial&lt;n, 0&gt; [with int n = 0]’
   19 | class Combinatorial&lt;n, 0&gt;
      |       ^~~~~~~~~~~~~~~~~~~
comb.cpp:8:61: error: incomplete type ‘Combinatorial&lt;0, 0&gt;’ used in nested name specifier
    8 |     static const int value = Combinatorial&lt;n - 1, m&gt;::value + Combinatorial&lt;n - 1, m - 1&gt;::value;
      |
</code></pre></div></section><footer class=article-footer><section class=article-tags><a href=/tags/c++/>C++</a>
<a href=/tags/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/>编程语言</a></section><section class=article-copyright><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-copyright" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="12" cy="12" r="9"/><path d="M14.5 9a3.5 4 0 100 6"/></svg><span>Licensed under CC BY-NC-SA 4.0</span></section></footer><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/katex.min.css integrity=sha384-RZU/ijkSsFbcmivfdRBQDtwuwVqK7GMOw6IMvKyeWL2K5UAlyp6WonmB8m7Jd0Hn crossorigin=anonymous><script src=https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/katex.min.js integrity=sha384-pK1WpvzWVBQiP0/GjnvRxV4mOb0oxFuyRxJlk6vVw146n3egcN5C925NCP7a7BY8 crossorigin=anonymous defer></script><script src=https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/contrib/auto-render.min.js integrity=sha384-vZTG03m+2yp6N6BNi5iM4rW4oIwk5DfcNdFfxkk9ZWpDriOkXX8voJBFrAO7MpVl crossorigin=anonymous defer></script><script>window.addEventListener("DOMContentLoaded",()=>{renderMathInElement(document.querySelector(`.article-content`),{delimiters:[{left:"$$",right:"$$",display:!0},{left:"$",right:"$",display:!1},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}]})})</script></article><aside class=related-contents--wrapper><h2 class=section-title>Related contents</h2><div class=related-contents><div class="flex article-list--tile"><article><a href=/posts/learning/rust-functional/><div class=article-details><h2 class=article-title>Rust 函数式编程</h2></div></a></article><article><a href=/posts/learning/rust-generic-types/><div class=article-details><h2 class=article-title>Rust 泛型</h2></div></a></article><article><a href=/posts/learning/rust-collections/><div class=article-details><h2 class=article-title>Rust 集合</h2></div></a></article><article><a href=/posts/learning/rust-modules/><div class=article-details><h2 class=article-title>Rust 模块与项目</h2></div></a></article><article><a href=/posts/learning/rust-onwership/><div class=article-details><h2 class=article-title>Rust 所有权特性</h2></div></a></article></div></div></aside><script src=https://utteranc.es/client.js repo=StardustDL/stardustdl.github.io issue-term=pathname label=comment crossorigin=anonymous async></script><style>.utterances{max-width:unset}</style><script>function setUtterancesTheme(b){let a=document.querySelector('.utterances iframe');a&&a.contentWindow.postMessage({type:'set-theme',theme:`github-${b}`},'https://utteranc.es')}addEventListener('message',a=>{if(a.origin!=='https://utteranc.es')return;setUtterancesTheme(document.documentElement.dataset.scheme)}),window.addEventListener('onColorSchemeChange',a=>{setUtterancesTheme(a.detail)})</script><footer class=site-footer><section class=copyright>&copy;
2017 -
2021 StardustDL's Blog</section><section class=powerby><a style=color:gray href=http://www.beian.miit.gov.cn>冀ICP备19021004号</a><br>Built with <a href=https://gohugo.io/ target=_blank rel=noopener>Hugo</a><br>Theme <b><a href=https://github.com/CaiJimmy/hugo-theme-stack target=_blank rel=noopener data-version=3.5.0>Stack</a></b> designed by <a href=https://jimmycai.com target=_blank rel=noopener>Jimmy</a></section></footer><div class=pswp tabindex=-1 role=dialog aria-hidden=true><div class=pswp__bg></div><div class=pswp__scroll-wrap><div class=pswp__container><div class=pswp__item></div><div class=pswp__item></div><div class=pswp__item></div></div><div class="pswp__ui pswp__ui--hidden"><div class=pswp__top-bar><div class=pswp__counter></div><button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title=Share></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button><div class=pswp__preloader><div class=pswp__preloader__icn><div class=pswp__preloader__cut><div class=pswp__preloader__donut></div></div></div></div></div><div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"><div class=pswp__share-tooltip></div></div><button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"></button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"></button><div class=pswp__caption><div class=pswp__caption__center></div></div></div></div></div><script src=https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js integrity="sha256-ePwmChbbvXbsO02lbM3HoHbSHTHFAeChekF1xKJdleo=" crossorigin=anonymous defer></script><script src=https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js integrity="sha256-UKkzOn/w1mBxRmLLGrSeyB4e1xbrp4xylgAWb3M42pU=" crossorigin=anonymous defer></script><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.css integrity="sha256-c0uckgykQ9v5k+IqViZOZKc47Jn7KQil4/MP3ySA3F8=" crossorigin=anonymous><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.css integrity="sha256-SBLU4vv6CA6lHsZ1XyTdhyjJxCjPif/TRkjnsyGAGnE=" crossorigin=anonymous></main><aside class="sidebar right-sidebar sticky"><section class="widget archives"><div class=widget-icon><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-hash" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentcolor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><line x1="5" y1="9" x2="19" y2="9"/><line x1="5" y1="15" x2="19" y2="15"/><line x1="11" y1="4" x2="7" y2="20"/><line x1="17" y1="4" x2="13" y2="20"/></svg></div><h2 class="widget-title section-title">Table of contents</h2><div class=widget--toc><nav id=TableOfContents><ol><li><ol><li><a href=#阶乘数列>阶乘数列</a></li><li><a href=#斐波那契数列>斐波那契数列</a></li><li><a href=#组合数>组合数</a></li></ol></li></ol></nav></div></section></aside></div><script src=https://cdn.jsdelivr.net/npm/node-vibrant@3.1.5/dist/vibrant.min.js integrity="sha256-5NovOZc4iwiAWTYIFiIM7DxKUXKWvpVEuMEPLzcm5/g=" crossorigin=anonymous defer></script><script type=text/javascript src=/ts/main.js defer></script><script>(function(){const a=document.createElement('link');a.href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&display=swap",a.type="text/css",a.rel="stylesheet",document.head.appendChild(a)})()</script></body></html>